package com.united.ucts.modules.juc.lock;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * JUC并发编程学习笔记样例代码
 *
 * @author hudan
 * @version 1.0
 * @filename ThreadNotifyDemo.java
 * @copyright <a href="www.chancein.com">www.chancein.com</a>
 * @date 2022-09-15
 */
@Slf4j
public class ThreadNotifyDemo {

    public static void main(String[] args) {
        // 一般情况下不做特殊说明配置,用户新建的线程都是用户线程
        Thread thread = new Thread(() -> {
            // 当前线程需要处理的业务逻辑
            System.out.println(Thread.currentThread().getName() + "\t 开始运行, " +
                    (Thread.currentThread().isDaemon() ? "守护线程" : "用户线程"));
            while (true) {
                System.out.println("进入死循环了,一直执行下去");
            }
        }, "this threa name: " + Thread.currentThread().getName() + "will start!");
        thread.start();

        /* 将当前线程暂停休眠几秒钟(默认3秒) */
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
            log.error("休眠当前线程:[{}]出现异常:[{}]", Thread.currentThread().getName(), e.getMessage());
        }
    }


    /**
     * 初始值
     */
    private int number = 0;

    /**
     * 具体的业务逻辑方法
     * 利用synchronized修饰的+1方法
     */
    @SneakyThrows
    private synchronized void incr() {
        // 判断 (如果将while改成if会出现线程虚假唤醒问题)
        while (number != 0) {
            // 在哪里睡,就在哪里行
            this.wait();
        }

        // 干活: 如果number的值是0,则执行+1操作
        number++;
        System.out.println(Thread.currentThread().getName() + "::" + number);

        // 通知: 通知其他线程
        this.notifyAll();
    }

    /**
     * 利用synchronized修饰的-1方法
     */
    @SneakyThrows
    private synchronized void decr() {
        // 第二步: 判断  干活  通知(如果将while改成if会出现线程虚假唤醒问题)
        while (number != 1) {
            this.wait();
        }

        // 如果number的值是1,则执行-1操作
        number++;
        System.out.println(Thread.currentThread().getName() + "::" + number);

        // 通知其他线程
        this.notifyAll();
    }
}

/**
 * 第一步： 创建资源类,定义属性和操作方法
 * @author hudan
 * @version 1.0
 * @filename Share.java
 * @copyright <a href="www.chancein.com">www.chancein.com</a>
 * @date 2022-09-15
 */
class Share {
    /** 全局成员变量 */
    private int number =0;
    /** 创建锁 */
    private Lock lock = new ReentrantLock();
    private java.util.concurrent.locks.Condition Condition = lock.newCondition();
}